<?php

namespace Xin\LaravelFortify\Plugin;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    use WithCurrentPlugin;

    /**
     * @return void
     */
    public function register()
    {
        $this->registerEnforceMorphMaps();

        $this->registerEvents();

        $this->registerCommands();

        $this->app->booted(function () {
            /** @var Schedule $schedule */
            $schedule = $this->app->make(Schedule::class);
            $this->registerCommandSchedules($schedule);
        });
    }

    /**
     * Boot the application events.
     */
    public function boot(): void
    {
        $this->registerTranslations();

        $this->registerConfig();

        $this->registerViews();

        if ($this->app->runningInConsole()) {
            $this->loadMigrationsFrom($this->databasePath('migrations'));
        }

        $this->registerRouteServiceProvider();
    }

    /**
     * Register enforce morph maps.
     */
    protected function registerEnforceMorphMaps()
    {
        // Relation::enforceMorphMap([]);
    }

    /**
     * 注册事件
     * @return void
     */
    protected function registerEvents()
    {
        // $this->listen('*', function ($event, $payload) {
        // });
    }

    /**
     * 监听事件
     * @param array $events
     * @return void
     */
    protected function listen(array $events)
    {
        foreach ($events as $event => $listeners) {
            foreach (array_unique($listeners, SORT_REGULAR) as $listener) {
                $this->emitter()->listen($event, $listener);
            }
        }
    }

    /**
     * @return Dispatcher
     */
    protected function emitter()
    {
        return $this->app['events'];
    }

    /**
     * 以 Command::class 格式注册命令
     */
    protected function registerCommands()
    {
        // $this->commands([]);
    }

    /**
     * 注册命令 Schedules。
     */
    protected function registerCommandSchedules(Schedule $schedule)
    {
        // $schedule->command('inspire')->hourly();
    }

    /**
     * 注册多语音
     */
    public function registerTranslations(): void
    {
        $pluginName = $this->getCurrentPluginName();
        $pluginNameLower = $this->getCurrentPluginName(true);

        $langPath = resource_path('lang/plugins/' . $pluginNameLower);

        if (is_dir($langPath)) {
            $this->loadTranslationsFrom($langPath, $pluginNameLower);
            $this->loadJsonTranslationsFrom($langPath);
        } else {
            $this->loadTranslationsFrom($this->basePath('lang'), $pluginNameLower);
            $this->loadJsonTranslationsFrom($this->basePath('lang'));
        }
    }

    /**
     * 注册 config。
     */
    protected function registerConfig()
    {
        // 没有特别的意义
        // $this->publishes([
        //    $this->configPath('config.php') => config_path($this->getCurrentPluginName(true) . '.php')
        // ], 'config');

        $this->mergeConfigFrom($this->configPath('config.php'), $this->getCurrentPluginName(true));
    }

    /**
     * 注册视图。
     */
    public function registerViews()
    {
        $pluginNameLower = $this->getCurrentPluginName(true);

        $viewPath = resource_path('views/plugins/' . $pluginNameLower);
        $sourcePath = $this->basePath('resources/views');

        $this->publishes(
            [
                $sourcePath => $viewPath,
            ],
            ['views', $pluginNameLower . '-plugin-views']
        );

        $this->loadViewsFrom(
            array_merge($this->getPublishableViewPaths(), [$sourcePath]),
            $pluginNameLower
        );

        $componentNamespace = str_replace('/', '\\', config('modules.namespace') . '\\' . $this->getCurrentPluginName() . '\\' . config('modules.paths.generator.component-class.path'));
        Blade::componentNamespace($componentNamespace, $pluginNameLower);
    }

    /**
     * @return array
     */
    private function getPublishableViewPaths()
    {
        $paths = [];

        $pluginNameLower = $this->getCurrentPluginName(true);
        foreach (config('view.paths') as $path) {
            if (is_dir($path . '/plugins/' . $pluginNameLower)) {
                $paths[] = $path . '/plugins/' . $pluginNameLower;
            }
        }

        return $paths;
    }

    /**
     * 注册路由提供者
     * @return void
     */
    protected function registerRouteServiceProvider()
    {
        $selfClass = get_class($this);
        $lastSlashIndex = strrpos($selfClass, '\\');
        $namespace = substr($selfClass, 0, $lastSlashIndex);
        $routeServiceProviderClass = "$namespace\\RouteServiceProvider";
        $this->app->register($routeServiceProviderClass);
    }

    /**
     * Get the services provided by the provider.
     */
    public function provides()
    {
        return [];
    }
}
